package com.apes.fico.masterdata.gl.model;

import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.DefaultPersistListener;
import com.apes.framework.jpa.Model;
import com.apes.framework.jpa.Name;
import com.apes.framework.jpa.comment.Comment;
import com.apes.framework.jpa.generator.ApesGenerator;
import com.apes.framework.plugin.soe.annotations.State;
import com.apes.framework.plugin.soe.annotations.States;
import com.apes.framework.util.ApesConst;
import com.apes.fico.masterdata.gl.respository.AccountingSystemRepository;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.SelectBeforeUpdate;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: apestech
 * @description: 会计科目表科目(集团科目表)
 * @author: Chengxm
 * @create: 2018-12-20 15:51
 **/
@Getter
@Setter
@SelectBeforeUpdate
@DynamicInsert
@DynamicUpdate
@Entity
@EntityListeners(DefaultPersistListener.class)
@Table(name = AccountingChart.CONST_TABLE_NAME, indexes = {
        @Index(columnList = "code,acc_system_id", unique = true)
})
public class AccountingChart extends Model {
    public final static String CONST_TABLE_NAME = "mas_acc_chart";
    @Id
    @Column(name = "id", length = 32)
    @ApesGenerator(code = CONST_TABLE_NAME, name = "会计科目表科目(集团科目表)")
    @Comment("编号")
    private String id;

    @Column(name = "code", length = 16)
    @Comment("科目代码")
    private String code;

    @Column(name = "name", length = 255)
    @Comment("科目名称")
    private String name;

    @Column(name = "display_name", nullable = false, length = 255)
    @Comment("科目显示名称")
    private String displayName;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parent_id", referencedColumnName = "id")
    @Comment("上级科目编码")
    private AccountingChart parent;

    @Column(name = "price", columnDefinition = ApesConst.FIELD_BOOLEAN_FALSE)
    @Comment("单价标记")
    private boolean price;

    @Column(name = "quantity", columnDefinition = ApesConst.FIELD_BOOLEAN_FALSE)
    @Comment("数量标记")
    private boolean quantity;

    @Comment("科目体系") //所属会计科目表
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "acc_system_id", referencedColumnName = "id")
    private AccountingSystem accSystem;

    @Column(name = "remcode", length = 16)
    @Comment("助记码")
    private String remcode;

    /*0:借:1:贷*/
    @Column(name = "balanorient", length = 1)
    @Comment("余额方向")
    @States(name = "余额方向", values = {
            @State(id = AccountingModel.DEBIT, name = "借方"),
            @State(id = AccountingModel.CREDIT, name = "贷方")})
    private String balanorient;

    @Comment("所属科目组")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "acc_group_id", referencedColumnName = "id")
    private AccountingGroup accGroup;

    @Comment("科目分类")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "acc_chart_type_id", referencedColumnName = "id")
    private AccountingChartType accountingChartType;

    @Comment("有效性")
    @Column(name = "valid", nullable = false, columnDefinition = "number(1,0) default 1")
    private boolean valid = true;

    @Comment("末级标记")
    @Column(name = "final_flag", nullable = false, columnDefinition = "number(1,0) default 0")
    private boolean finalFlag = false;

    @Comment("级次")
    @Column(name = "classes", columnDefinition = "number(1,0) default 1")
    private double classes;

    @Comment("现金分类(0=其它，1=现金科目，2=银行科目，3=现金等价物)")
    @Column(name = "cash_type", columnDefinition = "number(1,0) default 1")
    private int cashType;

    @Name
    @Comment("辅助核算标识")
    @Column(name = "aux_flag", nullable = false, columnDefinition = "number(1,0) default 0")
    private boolean auxFlag = false;

    @OneToMany(mappedBy = "accChart", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @OrderBy("sequence asc")
    private List<AccountingChartAuxiliary> accChartAuxiliaries = new ArrayList(); //辅助项

    public List<AccountingChartAuxiliary> getAccChartAuxiliaries() {
        if (accChartAuxiliaries == null) return new ArrayList<>();
        boolean bAux = false;
        for (AccountingChartAuxiliary item : accChartAuxiliaries) {
            item.setAccChart(this);
            bAux = true;
        }
        this.setAuxFlag(bAux);
        return accChartAuxiliaries;
    }

    public void checkAcl() {
        AccountingSystem accountingSystem = SpringManager.getBean(AccountingSystemRepository.class).findOne(this.getAccSystem().getId());
        String acl = accountingSystem.getAccIdRule();
        String[] acls = acl.split("/");
        int lenght = 0;  //编码规则制定的长度
        int ruledLength = 0;//级别规定的最大长度
        String code = this.getCode();  //当前代码
        for (int i = 0; i < acls.length; i++) {  //获得编码规则规定的最大长度 如4/2 =6
            lenght += Integer.parseInt(acls[i]);
        }
        if (this.getCode().length() > lenght)
            throw new RuntimeException("编码不符合规则,超出长度！请遵循" + accountingSystem.getAccIdRule());
        for (int i = 0; i < ((int) (this.classes)); i++) {  //获得级别规定的最大长度 如4/2 =6
            ruledLength += Integer.parseInt(acls[i]);
        }
        if (this.getCode().length() != ruledLength)
            throw new RuntimeException("编码不符合规则,不符合级别规定的长度！请遵循" + accountingSystem.getAccIdRule());
        if (this.getParent() != null) { //当存在上级科目时
            if (!code.substring(0, this.getParent().getCode().length()).equals(this.getParent().getCode()))
                throw new RuntimeException("编码不符合规则！请符合上级科目" + this.getParent().getCode());
        }
    }

    @Transient
    private String path;

    public String getPath() {
        AccountingModel model = new AccountingModel();
        return model.getPath(accSystem, code);
    }

}
